import java_cup.sym;
import java_cup.runtime.*;

%%

%standalone
%class LexicalAnalyzer
%line
%column
%state STRING
%cup

%{
	private StringBuilder stringBuilder;
	
  	public boolean hasNext() {
  		return !zzAtEOF;
  	}
	
	private Symbol symbol(int type, String typeName) {
    	return symbol(type, null, typeName);
  	}
  	
  	private Symbol symbol(int type, Object value, String typeName) {
    	return new Symbol(type, yyline, yycolumn, value);
  	}
%}

boolean = "true" | "false"
digit = [0-9]+
alpha = [a-zA-Z]
blank = [ \r\n\t\f]
int = {digit}
number = {int}\.{digit}([eE][+-]?[0-9]+)?
comment = --([^\n\r])*[\n\r]
id = ({alpha} | _)({alpha} | {digit} | _)*
collection = "Bag" | "Set" | "OrderedSet" | "Sequence"
collectionOp = "count" | "sum" | "size" | "notEmpty" | "any" | "exists" |
                "includesAll" | "excludesAll" | "forAll" | "collect" |
                "reject" | "select" | "excludes" | "excluding" | "isEmpty" |
                "includes" | "including" | "first" | "last" | "asSet" | "asBag" |
                "asSequence" | "asOrderedSet" | "isUnique" | "at"
stringDelim = \'

%%

<YYINITIAL> {comment}    		{/* do nothing */}
<YYINITIAL> {blank}    			{/* do nothing */}
<YYINITIAL> "("					{ return symbol(AnalisadorSimbolosOcl.PARENTLEFT, "PARENTLEFT"); }
<YYINITIAL> ")"					{ return symbol(AnalisadorSimbolosOcl.PARENTRIGHT, "PARENTRIGHT"); }
<YYINITIAL> "{"					{ return symbol(AnalisadorSimbolosOcl.CHAVELEFT, "CHAVELEFT"); }
<YYINITIAL> "}"					{ return symbol(AnalisadorSimbolosOcl.CHAVERIGHT, "CHAVERIGHT"); }
<YYINITIAL> "|"					{ return symbol(AnalisadorSimbolosOcl.PIPELINE, "PIPELINE"); }
<YYINITIAL> "."                 { return symbol(AnalisadorSimbolosOcl.DOT, "DOT"); }
<YYINITIAL> ","                 { return symbol(AnalisadorSimbolosOcl.COMMA, "COMMA"); }
<YYINITIAL> ":"					{ return symbol(AnalisadorSimbolosOcl.COLON, "COLON"); }
<YYINITIAL> "::"				{ return symbol(AnalisadorSimbolosOcl.COLONCOLON, "COLONCOLON"); }
<YYINITIAL> ">"					{ return symbol(AnalisadorSimbolosOcl.GREATER, "GREATER"); }
<YYINITIAL> ">="				{ return symbol(AnalisadorSimbolosOcl.GREATEREQUALS, "GREATEREQUALS"); }
<YYINITIAL> "<"					{ return symbol(AnalisadorSimbolosOcl.LESS, "LESS"); }
<YYINITIAL> "<="				{ return symbol(AnalisadorSimbolosOcl.LESSEQUALS, "LESSEQUALS"); }
<YYINITIAL> "="					{ return symbol(AnalisadorSimbolosOcl.EQUALS, "EQUALS"); }
<YYINITIAL> "<>"				{ return symbol(AnalisadorSimbolosOcl.DIFFERENT, "DIFFERENT"); }
<YYINITIAL> "and"				{ return symbol(AnalisadorSimbolosOcl.AND, "AND"); }
<YYINITIAL> "or"				{ return symbol(AnalisadorSimbolosOcl.OR, "OR"); }
<YYINITIAL> "xor"				{ return symbol(AnalisadorSimbolosOcl.XOR, "XOR"); }
<YYINITIAL> "not"				{ return symbol(AnalisadorSimbolosOcl.NOT, "NOT"); }
<YYINITIAL> "implies"			{ return symbol(AnalisadorSimbolosOcl.IMPLIES, "IMPLIES"); }
<YYINITIAL> "pre"				{ return symbol(AnalisadorSimbolosOcl.PRE, "PRE"); }
<YYINITIAL> "post"				{ return symbol(AnalisadorSimbolosOcl.POST, "POST"); }
<YYINITIAL> "context"			{ return symbol(AnalisadorSimbolosOcl.CONTEXT, "CONTEXT"); }
<YYINITIAL> "@pre"				{ return symbol(AnalisadorSimbolosOcl.ATPRE, "ATPRE"); }
<YYINITIAL> "self"				{ return symbol(AnalisadorSimbolosOcl.SELF, "SELF"); }
<YYINITIAL> "if"				{ return symbol(AnalisadorSimbolosOcl.IF, "IF"); }
<YYINITIAL> "then"				{ return symbol(AnalisadorSimbolosOcl.THEN, "THEN"); }
<YYINITIAL> "else"				{ return symbol(AnalisadorSimbolosOcl.ELSE, "ELSE"); }
<YYINITIAL> "endif"				{ return symbol(AnalisadorSimbolosOcl.ENDIF, "ENDIF"); }
<YYINITIAL> "->"				{ return symbol(AnalisadorSimbolosOcl.ACCESS, "ACCESS"); }
<YYINITIAL> {boolean}        	{ return symbol(AnalisadorSimbolosOcl.BOOL, new Boolean(yytext()), "BOOL"); }
<YYINITIAL> {int}        		{ return symbol(AnalisadorSimbolosOcl.INTEGER, new Integer(yytext()), "INTEGER"); }
<YYINITIAL> {number}    		{ return symbol(AnalisadorSimbolosOcl.REAL, new Double(yytext()), "REAL"); }
<YYINITIAL> {collection}	    { return symbol(AnalisadorSimbolosOcl.COLLECTION, yytext(), "collection"); }
<YYINITIAL> {collectionOp}	    { return symbol(AnalisadorSimbolosOcl.COLLECTIONOP, yytext(), "collectionOp"); }
<YYINITIAL> {id}				{ return symbol(AnalisadorSimbolosOcl.ID, yytext(), "ID"); }
<YYINITIAL> "+"					{ return symbol(AnalisadorSimbolosOcl.PLUS, "PLUS"); }
<YYINITIAL> "-"					{ return symbol(AnalisadorSimbolosOcl.MINUS, "MINUS"); }
<YYINITIAL> "*"					{ return symbol(AnalisadorSimbolosOcl.TIMES, "TIMES"); }
<YYINITIAL> "/"					{ return symbol(AnalisadorSimbolosOcl.DIVISION, "DIVISION"); }
<YYINITIAL> {stringDelim}		{ 
							  	  	 stringBuilder = new StringBuilder();
							  	  	 yybegin(STRING);
								}
									
<STRING> "\\\\"					{ stringBuilder.append("\\"); }
<STRING> "\\\'"					{ stringBuilder.append("'"); }
<STRING> [^\\\'] 				{ stringBuilder.append(yytext()); }
<STRING> <<EOF>>				{ throw new RuntimeException("Lexical Error: Misformed String"); }
<STRING> {stringDelim}			{ 
    						  	 	 yybegin(YYINITIAL);
    					      	  	 return symbol(AnalisadorSimbolosOcl.STRING, stringBuilder.toString(), "STRING");
    							}

.|\n							{ throw new RuntimeException("Token not found: <" + yytext() + "> line " + (yyline+1) + " column " + (yycolumn+1) + "!"); }